#version 450 core

in V2F
{
    vec3 p;
    vec3 n;
    vec3 l;
    vec3 v;
} v2f;

layout(std140, binding = 1) uniform _Light
{
    vec4 position;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
} light;

layout(std140, binding = 2) uniform _Material
{
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shiness;
} material;

layout(std140, binding = 3) uniform _Rim
{
    vec4 color;
    float power;
} rim;

out vec4 fragColor;

void main()
{
    vec3 n = normalize(v2f.n);
    vec3 v = normalize(v2f.v);
    vec3 l = normalize(v2f.l);

    // ambient
    vec4 ambient = light.ambient * material.ambient;

    // diffuse
    vec4 diffuse = light.diffuse * material.diffuse * max(0.0, dot(n, l));

    // specular
    //    vec3 ref = reflect(l, n);
    //    float spec = max(0.0, dot(v, ref));
    vec3 h = normalize(l + v);
    float spec = max(0.0, dot(n, h));
    vec4 specular = light.specular * material.specular * pow(spec, material.shiness);

    // rim
    float r = 1.0 - max(0.0, dot(n, v));
    r = smoothstep(0.0, 1.0, r);
    r = pow(r, rim.power);
    vec4 rimColor = rim.color * r;

    fragColor = ambient + diffuse + specular + rimColor;
}
